<?php
/**
 * This class represent an association between a user
 * and a role in a group.
 * The corresponding table in the database is "cb_roles_users",
 * represented by Application_Model_RolesUsersTable.
 * @package fr.ec-lyon.aeecl.codebar.application.model
 * @subpackage rolesusers
 * @author Théo Chamley
 */
class Application_Model_RolesUsers {

	protected static $_dbTable;
	protected static $_dbTableClass = 'Application_Model_RolesUsersTable';

	const VENDEUR_ID = 1;
	const ADMIN_ID = 2;

	/**
	 *
	 * Set the table name for Application_Model_Groupe
	 * @param String $dbTable the name of the class representing the table
	 * @throws Exception
	 */
	public static function setDbTable($dbTable) {
		if (is_string($dbTable)) {
			$dbTable = new $dbTable();
		}
		if (!$dbTable instanceof Zend_Db_Table_Abstract) {
			throw new Exception('Invalid table data gateway provided');
		}
		self::$_dbTable = $dbTable;
	}

	/**
	 *
	 * Get the table of the data base.
	 * @return the table of the database.
	 */
	public static function getDbTable() {
		if (null === self::$_dbTable) {
			self::setDbTable(self::$_dbTableClass);
		}
		return self::$_dbTable;
	}

	/**
	 *
	 * Get all the admins of a group, including the general admins.
	 * @param array $id_groupe
	 */
	public function getAdmins($id_groupe) {
		$rows = self::getDbTable()->fetchAll(self::getDbTable()->select()
		->where('id_role = ?', self::ADMIN_ID)
		->where('id_groupe = ?',$id_groupe));
		$results = array();
		foreach($rows as $r) {
			$results[] = $r['login'];
		}
		return $results;
	}

	/**
	 *
	 * Get all the admins of a group, excluding the general admins.
	 * @param int $id_group
	 * @return array An array of the logins of the said admins
	 */
	public static function getAdminsNotGeneral($id_group) {
		$results = array();
		$select = self::getDbTable()->select()->from(array('c'=> self::getDbTable()->getName()))
		->where('c.id_groupe = ?', $id_group)
		->where('c.id_role = ?', self::ADMIN_ID)
		//TODO better way to do this complex request?
		/*
		* The request looks like this:
		* SELECT * FROM cb_roles_users AS c WHERE c.id_role = 2
		* AND c.id_groupe = 3
		* AND (SELECT COUNT(*) FROM cb_roles_users WHERE
		* login = c.login
		* AND id_groupe = 1) = 0;
		*/
		->where('(SELECT COUNT(*) FROM '.self::getDbTable()->getName().' WHERE login = c.login AND id_groupe = '.self::ADMIN_ID.') = ?', 0);
		$rows = self::getDbTable()->fetchAll($select);
		foreach($rows as $r) {
			$user = Application_Model_User::getByLogin($r['login']);
			$results[$r['login']] = $user->getNom().' '.$user->getPrenom();
		}
		asort($results);
		return $results;
	}

	/**
	 *
	 * Get all the salesmen of the group.
	 * @param int $id_group
	 * @return array An array of the salesmen's logins
	 */
	public function getVendeurs($id_group)
	{
		$rows = self::getDbTable()->fetchAll(self::getDbTable()->select()->where('id_role = ?',1)->where('id_groupe = ?',$id_group));
		$results = array();
		foreach($rows as $r)
		{
			$results[] = $r['login'];
		}
		return $results;
	}

	/**
	 *
	 * Get all the salesmen and admins of the group.
	 * @param int $id_group
	 * @return array An array of the logins of those users
	 */
	public static function getMembres($id_group)
	{
		$rows = self::getDbTable()->fetchAll(self::getDbTable()->select()->where('id_groupe = ?', $id_group));
		$results = array();
		foreach($rows as $r) {
			$results[] = Application_Model_User::getByLogin($r['login']);
		}
		return $results;
	}

	/**
	 *
	 * Removes a salesman from the given group.
	 * @param int $id_group
	 * @param string $login
	 */
	public function removeVendeur($id_group, $login)
	{
		$n = self::getDbTable()->delete(array(
			 'id_groupe = ?' => $id_group,
			 'login = ?' => $login,
			 'id_role = ?' => 1
		));
		//suppresion du mot de passe si l'utilisateur n'est plus dans aucun groupe
		$rows = self::getDbTable()->fetchAll(self::getDbTable()->select()->where('login = ?',$login));
		//TODO: count en SQL.
		if(count($rows) == 0)
		{
			Application_Model_User::getByLogin($login)
			->changePwd('');
		}
		//inscription dans l'historique
		$g = new Application_Model_Groupe();
		$g->getByID($id_group);
		$r = new Application_Model_Role();
		$r = $r->fromId(1);
		$libelle = "Suppression de l'user ".$login." du groupe ".$g->getName()." et de son rôle ".$r->getName();
		$histo = new Application_Model_HistoSystemElement($libelle);
		$histo->AddToHistoSystem();
		return $n;
	}

	/**
	 *
	 * Removes an admin from the given group.
	 * @param int $id_group
	 * @param string $login
	 * @return bool true if the password was removed
	 */
	public function removeAdmin($id_group, $login)
	{
		$pwd_removed = false;
		$n = self::getDbTable()->delete(array(
			 'id_groupe = ?' => $id_group,
			 'login = ?' => $login,
			 'id_role = ?' => self::ADMIN_ID
		));
		//suppresion du mot de passe si l'utilisateur n'est plus dans aucun groupe
		$rows = self::getDbTable()->fetchAll(self::getDbTable()->select()->where('login = ?',$login));
		if(count($rows) == 0)
		{
			Application_Model_User::getByLogin($login)
			->changePwd(NULL);
			$pwd_removed = true;
		}
		//inscription dans l'historique
		$g = new Application_Model_Groupe();
		$g->getByID($id_group);
		$r = new Application_Model_Role();
		$r = $r->fromId(2);
		$libelle = "Suppression de l'user ".$login." du groupe ".$g->getName()." et de son rôle ".$r->getName();
		$histo = new Application_Model_HistoSystemElement($libelle);
		$histo->AddToHistoSystem();
		return $pwd_removed;
	}

	/**
	 *
	 * Add a user to a group with a given role.
	 * @param int $id_role
	 * @param string $login
	 * @param int $id_group
	 * @throws Zend_Exception
	 * @return string Explication of what happened.
	 */
	public function addMembre($id_role, $login, $id_group)
	{
		$data = array(
		'id_role' => $id_role,
		'login' => $login,
		'id_groupe' => $id_group
		);

		$rows = self::getDbTable()->fetchAll(self::getDbTable()->select()
		->where('login = ?',$login)
		->where('id_groupe = ?',$id_group));

		/*
		 * If the user has no role in the group
		 */
		if(count($rows) == 0) {
			self::getDbTable()->insert($data);
			/*
			 * inscription dans l'historique
			 */
			$g = new Application_Model_Groupe();
			$g->getByID($id_group);
			$r = new Application_Model_Role();
			$r = $r->fromId($id_role);
			$histo = new Application_Model_HistoSystemElement("Inscription de l'user ".$login.
			" dans le groupe ".$g->getName()." avec le rôle ".$r->getName());
			$histo->AddToHistoSystem();
			return $login." a été ajouté en tant qu'admin de ce groupe.";
		}
		/*
		 * If he is already both a saler and an admin
		 */
		else if(count($rows) == 2) {
			self::removeVendeur($id_group, $login);
			throw new Zend_Exception($login." était déjà vendeur et admin de ce groupe. Son rôle de vendeur a été supprimé.");
		}
		/*
		 * If the user has already one role, we check which one it is.
		 */
		else if(count($rows) == 1) {
			/*
			 * If the user is already an admin, we do nothing.
			 */
			if($rows[0]['id_role'] == self::ADMIN_ID) {
				throw new Zend_Exception($login." est déjà admin de ce groupe, rien n'a été fait.");
			}
			/*
			 * If the user is a saler, we adapt according to the role we want to add.
			 */
			else {
				switch ($id_role) {
					case self::ADMIN_ID:
						self::removeVendeur($id_group, $login);
						self::getDbTable()->insert($data);
						$g = new Application_Model_Groupe();
						$g->getByID($id_group);
						$r = new Application_Model_Role();
						$r = $r->fromId($id_role);
						$histo = new Application_Model_HistoSystemElement("Inscription de l'user ".$login.
						" dans le groupe ".$g->getName()." avec le rôle ".$r->getName());
						$histo->AddToHistoSystem();
						return $login." était vendeur de ce groupe : ce rôle a été supprimé et celui d'admin a été ajouté.";
						break;
					case self::VENDEUR_ID:
						throw new Zend_Exception($login." était déjà un vendeur, rien n'a été fait.");
						break;
					default:
						throw new Zend_Exception("You provided an inexistent role id (".$id_role."). You can only user 1 for saler and 2 for admin.");
						break;
				}
			}
		} else {
			throw new Zend_Exception($login." has already more than 2 role in this group and this is impossible. Contact the developpers!");
		}
	}

	/**
	 *
	 * This function checks if the login given in parameter is the login
	 * of a general admin of the system.
	 * @param string $login
	 */
	public function isAdminGeneral($login) {
		//TODO: count direct en SQL.
		$rows = self::getDbTable()->fetchAll(self::getDbTable()->select()->where('login = ?',$login)->where('id_groupe = ?',1)->where('id_role = ?',2));
		return (count($rows) != 0);
	}

	/**
	 *
	 * To know if a given user is member of a
	 * given group.
	 * @param Application_Model_User $user
	 * @param Application_Model_Groupe $group
	 * @return bool
	 */
	public static function isMembre($user, $group) {
		$db = new Application_Model_RolesUsersTable();
		$rows = $db->fetchAll($db->select()->where('login = ?',$user->getLogin())->where('id_groupe = ?',$group->getID()));
		return (count($rows) != 0);
	}
}